package it.unipd.dei.bd.icineasti.database;

import it.unipd.dei.bd.icineasti.resource.Palinsesto;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

/**
 * Restituisce tutte le istanze di palinsesti per un dato evento (o film)
 *
 * @author Mattia Coccato
 */
public class GetPalinsestiDatabase {

	/**
	 * Interrogazione al database.
	 */
	private static final String STATEMENT = "SELECT DISTINCT ON (palinsesto.dataora, palinsesto.codice) palinsesto.*, (spettacolo.codice IS NULL) as Modificabile" +
							" FROM palinsesto LEFT OUTER JOIN spettacolo ON palinsesto.codice = spettacolo.codicePalinsesto" + 
							" WHERE palinsesto.codiceEvento = ? AND (spettacolo.valido = TRUE OR spettacolo.valido IS NULL) ORDER BY palinsesto.dataora ASC, palinsesto.codice ASC;";


	private static final String STATEMENT_PER_SEDE = "SELECT DISTINCT ON (palinsesto.dataora, palinsesto.codice) palinsesto.*, spettacoliSede.codicepalinsesto IS NOT NULL as Assegnato " +
								"FROM palinsesto LEFT OUTER JOIN (" +
								"	SELECT spettacolo.codicepalinsesto " + 
								"	FROM spettacolo INNER JOIN r_proiettato ON r_proiettato.codicespettacolo = spettacolo.codice " +
								"	INNER JOIN sala ON r_proiettato.idsala = sala.idsala WHERE sala.codicesede = ? AND Spettacolo.valido = TRUE) As SpettacoliSede ON spettacoliSede.codicepalinsesto = palinsesto.codice " +
								"WHERE palinsesto.codiceevento = ? AND palinsesto.dataora > current_timestamp " +
								"ORDER BY palinsesto.dataora ASC, palinsesto.codice ASC; ";

	/* Query di esempio:


	*/

	private static final String STATEMENT_SINGOLO = "SELECT * FROM Palinsesto WHERE codice = ?;";
	
	/**
	 * Connessione al database
	 */
	private final Connection con;
	
	/**
	 * Risultati della ricerca
	 */
	private final List<Palinsesto> palinsesti;

	private final int codiceEvento;
	
	public GetPalinsestiDatabase(Connection con, int codiceEvento) {
		this.con = con;
		this.codiceEvento = codiceEvento;
		this.palinsesti = new ArrayList<Palinsesto>();
	}

	public List<Palinsesto> getPalinsesti() throws SQLException {

		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			pstmt = con.prepareStatement(STATEMENT);

			pstmt.setInt(1, codiceEvento);

			rs = pstmt.executeQuery();
			

			while (rs.next()) {
				Palinsesto pal = new Palinsesto( 
								rs.getInt("codice"), 
								rs.getTimestamp("dataora"),
								rs.getInt("codiceEvento"),
								rs.getBoolean("in3d")
					);
				pal.setModificabile(rs.getBoolean("modificabile"));
				palinsesti.add(pal);
			}
		} finally {
			if (rs != null) {
				rs.close();
			}

			if (pstmt != null) {
				pstmt.close();
			}

			con.close();
		}

		return palinsesti;
	}

	public Palinsesto getSingoloDaCodice(int codicePalinsesto) throws SQLException {
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		Palinsesto pal = null;

		try {
			pstmt = con.prepareStatement(STATEMENT_SINGOLO);

			pstmt.setInt(1, codicePalinsesto);

			rs = pstmt.executeQuery();
			

			while (rs.next()) {
				pal = new Palinsesto( 
								rs.getInt("codice"), 
								rs.getTimestamp("dataora"),
								rs.getInt("codiceEvento"),
								rs.getBoolean("in3d")
					);
			}
		} finally {
			if (rs != null) {
				rs.close();
			}

			if (pstmt != null) {
				pstmt.close();
			}

			con.close();
		}

		return pal;

	}

	/** Ritorna una lista di palinsesti futuri per una data sede. Setta anche l'attributo "assegnato" se trova eventi correttamente inseriti per la sede corrente
	  */
	public List<Palinsesto> getPalinsestiFuturiPerSede(int codiceSede) throws SQLException {
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			pstmt = con.prepareStatement(STATEMENT_PER_SEDE);

			pstmt.setInt(1, codiceSede);
			pstmt.setInt(2, codiceEvento);

			rs = pstmt.executeQuery();
			

			while (rs.next()) {
				Palinsesto pal = new Palinsesto( 
								rs.getInt("codice"), 
								rs.getTimestamp("dataora"),
								rs.getInt("codiceEvento"),

								rs.getBoolean("in3d")
					);
				pal.setAssegnato(rs.getBoolean("assegnato"));
				palinsesti.add(pal);
			}
		} finally {
			if (rs != null) {
				rs.close();
			}

			if (pstmt != null) {
				pstmt.close();
			}

			con.close();
		}

		return palinsesti;
	}
}
